﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using ElfTyping.General;

namespace ElfTyping.Animations
{
    public class RhysPortrait : FireEmblemPortraitAnimation
    {
        public RhysPortrait(bool isBig)
            : base(@"Textures\Characters\Rhys")
        {
            SadMouths = new Rectangle[] {
                                        new Rectangle(259, 87, 14, 11),
                                        new Rectangle(259, 102, 14, 11),
                                        new Rectangle(259, 117, 14, 11),
                                        new Rectangle(259, 102, 14, 11)
                                    };
            HappyMouths = new Rectangle[] {
                                        new Rectangle(278, 87, 14, 11),
                                        new Rectangle(278, 102, 14, 11),
                                        new Rectangle(278, 117, 14, 11),
                                        new Rectangle(278, 102, 14, 11)
                                    };

            LeftEyes = new Rectangle[] {
                                          new Rectangle(322, 97, 10, 8),
                                          new Rectangle(322, 109, 10, 8),
                                          new Rectangle(322, 122, 10, 8),
                                          new Rectangle(322, 109, 10, 8)
                                      };

            RightEyes = new Rectangle[] {
                                           new Rectangle(341, 97, 15, 7),
                                           new Rectangle(341, 109, 15, 7),
                                           new Rectangle(341, 122, 15, 7),
                                           new Rectangle(341, 109, 15, 7)
                                       };

            if (isBig)
            {
                MouthDestination = new Rectangle(82, 77, 14, 12); // these are probably off by some y's
                LeftEyeDestination = new Rectangle(73, 54, 10, 9);
                RightEyeDestination = new Rectangle(92, 54, 15, 8);
                Portrait = new Rectangle(10, 11, 192, 250);
            }
            else
            {
                MouthDestination = new Rectangle(286, 206, 14, 11);
                LeftEyeDestination = new Rectangle(277, 183, 10, 8);
                RightEyeDestination = new Rectangle(296, 183, 15, 7);
                Portrait = new Rectangle(242, 140, 130, 120);
            }

            Frames = new List<Rectangle>() { Portrait };

            Initialize();
        }
        
    }

    public class SorenPortrait : FireEmblemPortraitAnimation
    {
        public SorenPortrait(bool isBig)
            : base(@"Textures\Characters\Soren")
        {
            SadMouths = new Rectangle[] {
                                        new Rectangle(234, 49, 12, 13),
                                        new Rectangle(234, 65, 12, 13),
                                        new Rectangle(234, 81, 12, 13),
                                        new Rectangle(234, 65, 12, 13)
                                    };
            HappyMouths = new Rectangle[] {
                                        new Rectangle(219, 49, 12, 13),
                                        new Rectangle(219, 65, 12, 13),
                                        new Rectangle(219, 81, 12, 13),
                                        new Rectangle(219, 65, 12, 13)
                                    };

            LeftEyes = new Rectangle[] {
                                          new Rectangle(164, 16, 12, 9),
                                          new Rectangle(164, 28, 12, 9),
                                          new Rectangle(164, 40, 12, 9),
                                          new Rectangle(164, 28, 12, 9)
                                      };

            RightEyes = new Rectangle[] {
                                           new Rectangle(183, 15, 15, 8),
                                           new Rectangle(183, 28, 15, 8),
                                           new Rectangle(183, 40, 15, 8),
                                           new Rectangle(183, 28, 15, 8)
                                       };

            if (isBig)
            {
                MouthDestination = new Rectangle(51, 58, 12, 13);
                LeftEyeDestination = new Rectangle(41, 39, 12, 9);
                RightEyeDestination = new Rectangle(60, 39, 15, 8);
                Portrait = new Rectangle(0, 0, 158, 210);
            }
            else
            {
                MouthDestination = new Rectangle(247, 156, 13, 13);
                LeftEyeDestination = new Rectangle(237, 137, 12, 9);
                RightEyeDestination = new Rectangle(256, 137, 15, 8);
                Portrait = new Rectangle(218, 98, 106, 112);
            }

            Frames = new List<Rectangle>() { Portrait };

            Initialize();
        }

    }

    public class ShinonPortrait : FireEmblemPortraitAnimation
    {
        public ShinonPortrait(bool isBig)
            : base(@"Textures\Characters\Shinon")
        {
            SadMouths = new Rectangle[] {
                                        new Rectangle(255, 53, 15, 10),
                                        new Rectangle(255, 67, 15, 10),
                                        new Rectangle(255, 81, 15, 10),
                                        new Rectangle(255, 67, 15, 10)
                                    };
            HappyMouths = new Rectangle[] {
                                        new Rectangle(274, 53, 15, 10),
                                        new Rectangle(274, 67, 15, 10),
                                        new Rectangle(274, 81, 15, 10),
                                        new Rectangle(274, 67, 15, 10)
                                    };

            LeftEyes = new Rectangle[] {
                                          new Rectangle(319, 61, 9, 6),
                                          new Rectangle(319, 71, 9, 6),
                                          new Rectangle(319, 82, 9, 6),
                                          new Rectangle(319, 71, 9, 6)
                                      };

            RightEyes = new Rectangle[] {
                                           new Rectangle(336, 60, 15, 7),
                                           new Rectangle(336, 70, 15, 7),
                                           new Rectangle(336, 81, 15, 7),
                                           new Rectangle(336, 70, 15, 7)
                                       };

            if (isBig)
            {
                MouthDestination = new Rectangle(65, 69, 15, 10);
                LeftEyeDestination = new Rectangle(55, 48, 9, 6);
                RightEyeDestination = new Rectangle(72, 47, 15, 7);
                Portrait = new Rectangle(0, 0, 201, 256);
            }
            else
            {
                MouthDestination = new Rectangle(295, 203, 15, 10);
                LeftEyeDestination = new Rectangle(285, 182, 9, 6);
                RightEyeDestination = new Rectangle(302, 181, 15, 8);
                Portrait = new Rectangle(261, 134, 139, 122);
            }

            Frames = new List<Rectangle>() { Portrait };

            Initialize();
        }

    }

    public class ReysonPortrait : FireEmblemPortraitAnimation
    {
        public ReysonPortrait(bool isBig)
            : base(@"Textures\Characters\Reyson")
        {
            SadMouths = new Rectangle[] {
                                        new Rectangle(273, 83, 13, 13),
                                        new Rectangle(273, 100, 13, 13),
                                        new Rectangle(273, 117, 13, 13),
                                        new Rectangle(273, 100, 13, 13),
                                    };
            HappyMouths = new Rectangle[] {
                                        new Rectangle(291, 83, 13, 13),
                                        new Rectangle(291, 100, 13, 13),
                                        new Rectangle(291, 117, 13, 13),
                                        new Rectangle(291, 100, 13, 13),
                                    };

            LeftEyes = new Rectangle[] {
                                          new Rectangle(334, 93, 11, 8),
                                          new Rectangle(334, 105, 11, 8),
                                          new Rectangle(334, 118, 11, 8),
                                          new Rectangle(334, 105, 11, 8),
                                      };

            RightEyes = new Rectangle[] {
                                          new Rectangle(350, 93, 15, 8),
                                          new Rectangle(350, 105, 15, 8),
                                          new Rectangle(350, 118, 15, 8),
                                          new Rectangle(350, 105, 15, 8),
                                       };

            if (isBig)
            {
                MouthDestination = new Rectangle(73, 100, 13, 13);
                LeftEyeDestination = new Rectangle(63, 79, 11, 8);
                RightEyeDestination = new Rectangle(83, 78, 15, 8);
                Portrait = new Rectangle(21, 10, 233, 250);
            }
            else
            {
                MouthDestination = new Rectangle(353, 202, 13, 13);
                LeftEyeDestination = new Rectangle(343, 181, 11, 8);
                RightEyeDestination = new Rectangle(363, 180, 15, 8);
                Portrait = new Rectangle(319, 140, 125, 120);
            }

            Frames = new List<Rectangle>() { Portrait };

            Initialize();
        }

    }

    public class TibarnPortrait : FireEmblemPortraitAnimation
    {
        public TibarnPortrait(bool isBig)
            : base(@"Textures\Characters\Tibarn")
        {
            SadMouths = new Rectangle[] {
                                        new Rectangle(337, 112, 28, 15),
                                        new Rectangle(337, 131, 28, 15),
                                        new Rectangle(337, 150, 28, 15),
                                        new Rectangle(337, 131, 28, 15),
                                    };
            HappyMouths = new Rectangle[] {
                                        new Rectangle(370, 112, 28, 15),
                                        new Rectangle(370, 131, 28, 15),
                                        new Rectangle(370, 150, 28, 15),
                                        new Rectangle(370, 131, 28, 15),
                                    };

            LeftEyes = new Rectangle[] {
                                          new Rectangle(433, 125, 10, 6),
                                          new Rectangle(433, 137, 10, 6),
                                          new Rectangle(433, 150, 10, 6),
                                          new Rectangle(433, 137, 10, 6),
                                      };

            RightEyes = new Rectangle[] {
                                          new Rectangle(451, 124, 9, 9),
                                          new Rectangle(451, 136, 9, 9),
                                          new Rectangle(451, 149, 9, 9),
                                          new Rectangle(451, 136, 9, 9),
                                       };

            if (isBig)
            {
                MouthDestination = new Rectangle(101, 96, 28, 15);
                LeftEyeDestination = new Rectangle(94, 76, 10, 6);
                RightEyeDestination = new Rectangle(117, 76, 9, 9);
                Portrait = new Rectangle(7, 13, 281, 297);
            }
            else
            {
                MouthDestination = new Rectangle(370, 258, 28, 15);
                LeftEyeDestination = new Rectangle(363, 238, 10, 6);
                RightEyeDestination = new Rectangle(386, 238, 9, 9);
                Portrait = new Rectangle(308, 182, 175, 128);
            }

            Frames = new List<Rectangle>() { Portrait };

            Initialize();
        }

    }

    public class FireEmblemPortraitAnimation : Animation
    {
        const float TotalTalkingTime = .67f;
        const float MinBlinkingTime = 4f;
        const float MaxBlinkingTime = 8f;
        const float TotalBlinkingTime = .33f;

        public static Point BigPortraitLeftPosition = new Point(142, TextBox.Top);
        public static Point BigPortraitRightPosition = new Point(475, TextBox.Top);

        protected Rectangle[] SadMouths;
        protected Rectangle[] HappyMouths;
        protected Rectangle MouthDestination;

        protected Rectangle[] LeftEyes;
        protected Rectangle LeftEyeDestination;

        protected Rectangle[] RightEyes;
        protected Rectangle RightEyeDestination;


        private bool _isSpeaking;
        public bool IsSpeaking
        {
            get { return _isSpeaking; }
            set
            {
                _isSpeaking = value;
                if (!_isSpeaking)
                {
                    talkingTime = 0;
                }
            }
        }
        public bool IsBlinking { get; set; }
        public bool IsActive { get; set; }
        public bool IsHappy
        {
            set { currentMouths = value ? HappyMouths : SadMouths; }
        }

        protected Rectangle Portrait { get; set; }
        private Point[] LeftEyeOffsets { get; set; }
        private Point[] RightEyeOffsets { get; set; }
        private Point[] MouthOffsets { get; set; }

        private float talkingTime = 0;
        private float waitingToBlinkTime = 0;
        private float blinkingTime = 0;
        private Random random = new Random();

        private Rectangle[] currentMouths;

        public FireEmblemPortraitAnimation(string imageFile)
            : base(imageFile)
        {            
        }

        protected void Initialize()
        {
            IsSpeaking = false;
            IsBlinking = true;
            IsHappy = true;
            IsActive = true;

            LeftEyeOffsets = new Point[] {                
                new Point(LeftEyeDestination.Left, LeftEyeDestination.Top),
                new Point(Portrait.Left + Portrait.Width - (LeftEyeDestination.Left - Portrait.Left) - LeftEyeDestination.Width, LeftEyeDestination.Top),
            };

            RightEyeOffsets = new Point[] {                
                new Point(RightEyeDestination.Left, RightEyeDestination.Top),
                new Point(Portrait.Left + Portrait.Width - (RightEyeDestination.Left - Portrait.Left) - RightEyeDestination.Width, RightEyeDestination.Top),
            };

            MouthOffsets = new Point[] {                
                new Point(MouthDestination.Left, MouthDestination.Top),
                new Point(Portrait.Left + Portrait.Width - (MouthDestination.Left - Portrait.Left) - MouthDestination.Width, MouthDestination.Top),
            };
        }

        public override void Advance(float dt)
        {
            if (IsSpeaking)
            {
                talkingTime += dt;
                if (talkingTime > TotalTalkingTime)
                {
                    talkingTime -= TotalTalkingTime;
                }
            }

            if (IsBlinking)
            {
                if (waitingToBlinkTime > 0 && blinkingTime <= 0)
                {
                    waitingToBlinkTime -= dt;

                    if (waitingToBlinkTime < 0)
                    {
                        blinkingTime = TotalBlinkingTime;
                    }
                }
                else if (blinkingTime > 0 && waitingToBlinkTime <= 0)
                {
                    blinkingTime -= dt;
                }
                else
                {
                    waitingToBlinkTime = (float)random.NextDouble() * (MaxBlinkingTime - MinBlinkingTime) + MinBlinkingTime;                    
                }
            }

            base.Advance(dt);
        }

        public void DrawWithBottomLeft(Camera camera, Point bottomLeft)
        {
            Rectangle destination = new Rectangle(bottomLeft.X, bottomLeft.Y - Portrait.Height, Portrait.Width, Portrait.Height);
            Draw(camera, destination);
        }

        public override void Draw(Camera camera, Rectangle destination, Color color, float depth)
        {
            color = IsActive ? Color.White : Color.Gray;

            base.Draw(camera, destination, color, depth);

            Rectangle leftEyeFrame = LeftEyes[0];
            Rectangle rightEyeFrame = RightEyes[0];
            Rectangle mouthFrame = currentMouths[0];

            if (IsSpeaking)
            {
                int frameIndex = (int)MathHelper.Clamp((talkingTime / TotalTalkingTime * 4), 0, 3);
                mouthFrame = currentMouths[frameIndex];
            }

            if (IsBlinking)
            {
                int frameIndex = (int)MathHelper.Clamp((blinkingTime / TotalBlinkingTime * 4), 0, 3);
                leftEyeFrame = LeftEyes[frameIndex];
                rightEyeFrame = RightEyes[frameIndex];
            }
            
            Rectangle leftEyeDestination = LeftEyeDestination;
            leftEyeDestination.Offset(-LeftEyeDestination.Left, -LeftEyeDestination.Top);
            leftEyeDestination.Offset(FlippedHorizontally ? LeftEyeOffsets[1] : LeftEyeOffsets[0]);
            leftEyeDestination.Offset(-Portrait.Left, -Portrait.Top);
            leftEyeDestination.Offset(destination.Location);            

            Rectangle rightEyeDestination = RightEyeDestination;
            rightEyeDestination.Offset(-RightEyeDestination.Left, -RightEyeDestination.Top);
            rightEyeDestination.Offset(FlippedHorizontally ? RightEyeOffsets[1] : RightEyeOffsets[0]);
            rightEyeDestination.Offset(-Portrait.Left, -Portrait.Top);
            rightEyeDestination.Offset(destination.Location);

            Rectangle mouthDestination = MouthDestination;
            mouthDestination.Offset(-MouthDestination.Left, -MouthDestination.Top);
            mouthDestination.Offset(FlippedHorizontally ? MouthOffsets[1] : MouthOffsets[0]);
            mouthDestination.Offset(-Portrait.Left, -Portrait.Top);
            mouthDestination.Offset(destination.Location);
            
            camera.DrawRectangleUV(leftEyeDestination, texture, leftEyeFrame, color, FlippedHorizontally);
            camera.DrawRectangleUV(rightEyeDestination, texture, rightEyeFrame, color, FlippedHorizontally);
            camera.DrawRectangleUV(mouthDestination, texture, mouthFrame, color, FlippedHorizontally);
        }
    }
}
